﻿using System;
using System.IO;
using Moq;
using StructureMap.AutoMocking;
using WikiPlex.Contrib.Services;
using Xunit;

namespace WikiPlex.Contrib.Facts
{
    public class RunnerFacts
    {
        [Fact]
        public void ShouldReturnTrueIfNoSourceFiles()
        {
            var mocks = new MoqAutoMocker<Runner>();
            Runner runner = mocks.ClassUnderTest;

            bool result = runner.Execute(new string[0], @"C:\SomePath", null);

            Assert.True(result);
        }

        [Fact]
        public void ShouldThrowArgumentNullExceptionIfOutputPathIsNull()
        {
            var mocks = new MoqAutoMocker<Runner>();
            Runner runner = mocks.ClassUnderTest;

            var ex = Record.Exception(() => runner.Execute(new string[0], null, null)) as ArgumentNullException;

            Assert.NotNull(ex);
        }

        [Fact]
        public void ShouldThrowArgumentExceptionIfOutputPathIsEmpty()
        {
            var mocks = new MoqAutoMocker<Runner>();
            Runner runner = mocks.ClassUnderTest;

            var ex = Record.Exception(() => runner.Execute(new string[0], string.Empty, null)) as ArgumentException;

            Assert.NotNull(ex);
        }

        [Fact]
        public void ShouldCreateOutputDirectory()
        {
            var mocks = new MoqAutoMocker<Runner>();
            Mock<IFileSystemService> fileSystem = Mock.Get(mocks.Get<IFileSystemService>());
            Runner runner = mocks.ClassUnderTest;

            runner.Execute(new[] {@"c:\file.txt"}, @"c:\temp", null);

            fileSystem.Verify(x => x.CreateDirectory(@"c:\temp"));
        }

        [Fact]
        public void ShouldWriteRenderedWikiText()
        {
            var mocks = new MoqAutoMocker<Runner>();
            Mock<IFileSystemService> fileSystem = Mock.Get(mocks.Get<IFileSystemService>());
            Mock<IWikiEngine> wikiEngine = Mock.Get(mocks.Get<IWikiEngine>());
            fileSystem.Setup(x => x.ReadAllText(@"c:\file.txt")).Returns("input");
            wikiEngine.Setup(x => x.Render("input")).Returns("output");

            bool result = mocks.ClassUnderTest.Execute(new[] {@"c:\file.txt"}, @"c:\temp", null);

            Assert.True(result);
            fileSystem.Verify(x => x.WriteAllText(@"c:\temp\file.html", "<html><body>output</body></html>"));
        }

        [Fact]
        public void AnyExceptionWillReturnFalse()
        {
            var mocks = new MoqAutoMocker<Runner>();
            Mock<IFileSystemService> fileSystem = Mock.Get(mocks.Get<IFileSystemService>());
            fileSystem.Setup(x => x.ReadAllText(It.IsAny<string>())).Throws<IOException>();

            bool result = mocks.ClassUnderTest.Execute(new[] {@"c:\file.txt"}, @"c:\temp", null);

            Assert.False(result);
        }

        [Fact]
        public void WillUseTemplateWhenRendering()
        {
            var mocks = new MoqAutoMocker<Runner>();
            Mock<IFileSystemService> fileSystem = Mock.Get(mocks.Get<IFileSystemService>());
            Mock<IWikiEngine> wikiEngine = Mock.Get(mocks.Get<IWikiEngine>());
            fileSystem.Setup(x => x.ReadAllText(@"c:\file.txt")).Returns("input");
            fileSystem.Setup(x => x.FileExists(@"c:\template.txt")).Returns(true);
            fileSystem.Setup(x => x.ReadAllText(@"c:\template.txt")).Returns("<html><body><div class=\"content\"><wiki:content /></div></body></html>");
            wikiEngine.Setup(x => x.Render("input")).Returns("output");

            mocks.ClassUnderTest.Execute(new[] {@"c:\file.txt"}, @"c:\temp", @"c:\template.txt");

            fileSystem.Verify(x => x.WriteAllText(@"c:\temp\file.html", "<html><body><div class=\"content\">output</div></body></html>"));
        }
    }
}